package com.budwk.app.enterprise.component;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.budwk.app.base.utils.StrUtil;
import com.budwk.app.domain.vo.IncomeStatementVo;
import com.budwk.app.enterprise.enums.IncomeFillTypeEnum;
import com.budwk.app.enterprise.models.IncomeStatementBase;
import com.budwk.app.enterprise.models.IncomeStatementBaseDetail;
import com.budwk.app.enterprise.services.BusinessinformationService;
import com.budwk.app.enterprise.services.IncomeStatementBaseService;
import com.budwk.app.exception.AppException;
import com.budwk.app.miniapp.common.CommonConstants;
import com.budwk.app.miniapp.utils.NutzIocUtils;
import com.budwk.app.miniapp.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;

@IocBean
@Slf4j
public class IncomeStatementComponent {

    @Inject
    private BusinessinformationService businessinformationService;

    public void checkAddParam(IncomeStatementVo statementVo) {
        if (statementVo.getFillType() == null) {
            throw new AppException("填报类型不能为空！");
        }
        if (statementVo.getFillYear() == null) {
            throw new AppException("填报年份不能为空！");
        }
        if (statementVo.getFillValue() == null) {
            throw new AppException("填报值不能为空！");
        }
        if (StringUtils.isEmpty(statementVo.getCompanyId())) {
            throw new AppException("填报企业不能为空！");
        }
        buildFillDate(statementVo);
        // 检查是否填报过
        IncomeStatementBaseService incomeStatementBaseService = NutzIocUtils.getBean(IncomeStatementBaseService.class);
        IncomeStatementBase data = incomeStatementBaseService.getFillData(statementVo, null);
        if (data != null) {
            throw new AppException("当前单位已填报过，请到填报处修改！");
        }
        statementVo.setOperatingRevenue(StrUtil.formatStr(statementVo.getOperatingRevenue()))
                .setOperatingProfit(StrUtil.formatStr(statementVo.getOperatingProfit()))
                .setProfitTotal(StrUtil.formatStr(statementVo.getProfitTotal()))
                .setNetProfit(StrUtil.formatStr(statementVo.getNetProfit()))
                .setOtherProfit(StrUtil.formatStr(statementVo.getOtherProfit()))
                .setComprehensiveTotal(StrUtil.formatStr(statementVo.getComprehensiveTotal()))
                .setFinancialExpenses(StrUtil.formatStr(statementVo.getFinancialExpenses()))
                .setLessOperatingCosts(StrUtil.formatStr(statementVo.getLessOperatingCosts()));
    }

    public void checkUpdateParam(IncomeStatementVo statementVo) {
        if (StringUtils.isEmpty(statementVo.getId())) {
            throw new AppException("填报id不能为空！");
        }
        buildFillDate(statementVo);
        // 检查是否填报过
        IncomeStatementBaseService incomeStatementBaseService = NutzIocUtils.getBean(IncomeStatementBaseService.class);
        IncomeStatementBase data = incomeStatementBaseService.getFillData(statementVo, null);
        if (data != null && !data.getId().equals(statementVo.getId())) {
            throw new AppException("当前单位已填报过，请到填报处修改！");
        }
        statementVo.setOperatingRevenue(StrUtil.formatStr(statementVo.getOperatingRevenue()))
                .setOperatingProfit(StrUtil.formatStr(statementVo.getOperatingProfit()))
                .setProfitTotal(StrUtil.formatStr(statementVo.getProfitTotal()))
                .setNetProfit(StrUtil.formatStr(statementVo.getNetProfit()))
                .setOtherProfit(StrUtil.formatStr(statementVo.getOtherProfit()))
                .setComprehensiveTotal(StrUtil.formatStr(statementVo.getComprehensiveTotal()))
                .setFinancialExpenses(StrUtil.formatStr(statementVo.getFinancialExpenses()))
                .setLessOperatingCosts(StrUtil.formatStr(statementVo.getLessOperatingCosts()));
    }

    // 如果是横线 则返回0
    public BigDecimal formatValueZero(String data) {
        if (CommonConstants.HORIAONTAL.equals(data)) {
            return new BigDecimal(0);
        }
        return new BigDecimal(data);
    }

    // 判斷除数是否为0或为空
    private boolean isDivideZero(String data) {
        if (StringUtils.isEmpty(data) || CommonConstants.HORIAONTAL.equals(data)) {
            return true;
        }
        return false;
    }

    // 计算销售净利率和销售毛利率
    private void calSalesRate(IncomeStatementVo statementVo) {
        // 1 销售净利率 净利润÷销售收入*100%   销售收入=营业收入
        if (isDivideZero(statementVo.getOperatingRevenue())) {
            statementVo.setMarginSales(CommonConstants.HORIAONTAL);
            statementVo.setGrossSales(CommonConstants.HORIAONTAL);
            return;
        }
        // 销售净利率计算公式：净利润÷销售收入*100%   销售收入=营业收入
        BigDecimal marginSales = formatValueZero(statementVo.getNetProfit())
                .divide(formatValueZero(statementVo.getOperatingRevenue()), 4, RoundingMode.HALF_UP);
        statementVo.setMarginSales(StrUtil.convertToPercentage(marginSales));
        // 2 销售毛利率 计算公式  [(销售收入-销售成本)÷销售收入]*100% 销售成本=营业成本
        BigDecimal grossSales = (formatValueZero(statementVo.getOperatingRevenue()).subtract(formatValueZero(statementVo.getLessOperatingCosts())))
                .divide(formatValueZero(statementVo.getOperatingRevenue()), 4, RoundingMode.HALF_UP);
        statementVo.setGrossSales(StrUtil.convertToPercentage(grossSales));
    }

    // 计算已获利息倍数  公式：净利润÷利息支出  息税前利润=净利润；利息支出是财务费用中的部分
    private void calInterestMultiple(IncomeStatementVo statementVo) {
        if (isDivideZero(statementVo.getFinancialExpenses())) {
            statementVo.setInterestCoverage(CommonConstants.HORIAONTAL);
            return;
        }
        BigDecimal interestCoverage = formatValueZero(statementVo.getNetProfit())
                .divide(formatValueZero(statementVo.getFinancialExpenses()), 4, RoundingMode.HALF_UP);
        statementVo.setInterestCoverage(StrUtil.convertToPercentage(interestCoverage));
    }

    public void cal(IncomeStatementVo statementVo) {
        // 1 计算销售净利率和销售毛利率
        calSalesRate(statementVo);
        // 2 已获利息倍数  净利润÷利息支出  息税前利润=净利润；利息支出是财务费用中的部分
        calInterestMultiple(statementVo);
        // 4 本年营业收入增长额÷上年营业收入总额*100%		本年营业收入增长额=本年营业收入额-上年营业收入额
        if (IncomeFillTypeEnum.ONE.getCode().equals(statementVo.getFillType())) {
            // 获取上一个月的数据
            LocalDate fillDate = LocalDateTimeUtil.parseDate(statementVo.getFillDate(), "yyyy年MM月");
            String lastMonth = LocalDateTimeUtil.format(fillDate.minusMonths(1L), "yyyy年MM月");
            buildRevenueGrowth(statementVo, lastMonth);
            return;
        }
        if (IncomeFillTypeEnum.THREE.getCode().equals(statementVo.getFillType())) {
            String lastValue = getLastQuartersFillDate(statementVo);
            buildRevenueGrowth(statementVo, lastValue);
            return;
        }
        if (IncomeFillTypeEnum.FIVE.getCode().equals(statementVo.getFillType())) {
            buildRevenueGrowth(statementVo, String.valueOf(statementVo.getFillYear() - 1) + "年");
        }
    }

    // 构建填报时间
    public static void buildFillDate(IncomeStatementVo statementVo) {
        Integer fillType = statementVo.getFillType();
        Integer fillYear = statementVo.getFillYear();
        Integer fillValue = statementVo.getFillValue();
        // 按照公司信息查询上一条数据
        if (IncomeFillTypeEnum.ONE.getCode().equals(fillType)) {
            statementVo.setFillDate(String.format("%s%s%s", statementVo.getFillYear(), "年", fillValue < 10 ? "0" + fillValue + "月": fillValue + "月"));
            return;
        }
        if (IncomeFillTypeEnum.THREE.getCode().equals(fillType)) {
            statementVo.setFillDate(String.format(IncomeFillTypeEnum.FORAMT_AUARTE, fillYear, formatQuartersToUpper(fillValue)));
            return;
        }
        if (IncomeFillTypeEnum.FIVE.getCode().equals(fillType)) {
            // 季度统计 查询上月的统计数据
            statementVo.setFillDate(String.format("%s%s", fillYear, "年"));
        }
    }

    // 获取上一季度的填报时间
    private String getLastQuartersFillDate(IncomeStatementVo statementVo) {
        Integer fillValue = statementVo.getFillValue();
        Integer fillYear = statementVo.getFillYear();
        if (1 == fillValue) {
            // 如果是第1季度
            return String.format(IncomeFillTypeEnum.FORAMT_AUARTE, fillYear - 1, formatQuartersToUpper(4));
        }
        return String.format(IncomeFillTypeEnum.FORAMT_AUARTE, fillYear, formatQuartersToUpper(fillValue - 1));
    }

    // 将季度的1234转为大写的一二三四
    private static String formatQuartersToUpper(Integer fillValue) {
        Integer[] lowData = {1 ,2, 3, 4}; // 小写
        String[] upperData = {"一" ,"二", "三", "四"}; // 大写
        String fillValueStr = String.valueOf(fillValue);
        for (int i = 0; i < lowData.length; i++) {
            if (lowData[i].equals(fillValue)) {
                fillValueStr = upperData[i];
                return fillValueStr;
            }
        }
        return fillValueStr;
    }

    /**
     * 构建营业收入增长率
     * @param statementVo 请求入参
     * @param lastValue 上一条数据填报时间
     */
    private void buildRevenueGrowth(IncomeStatementVo statementVo, String lastValue) {
        // 查询上一条数据
        IncomeStatementBaseService statementBaseService = NutzIocUtils.getBean(IncomeStatementBaseService.class);
        IncomeStatementBase lastBase = statementBaseService.getFillData(statementVo, lastValue);
        if (lastBase == null) {
            statementVo.setRevenueGrowth(CommonConstants.HORIAONTAL);
            return;
        }
        // 计算本年的本年营业收入增长额  本年营业收入增长额=本年营业收入额-上年营业收入额
        if (isDivideZero(lastBase.getOperatingRevenue())) {
            statementVo.setRevenueGrowth(CommonConstants.HORIAONTAL);
            return;
        }
        BigDecimal revenueGrowth = (formatValueZero(statementVo.getOperatingRevenue()).subtract(formatValueZero(lastBase.getOperatingRevenue())))
                .divide(formatValueZero(lastBase.getOperatingRevenue()), 4, RoundingMode.HALF_UP);
        statementVo.setRevenueGrowth(StrUtil.convertToPercentage(revenueGrowth));
    }
}
